// Copyright (c) 2007 Robin Boerdijk. All rights reserved.
//
// This software is licensed under the terms of the Microsoft Reciprocal License as described 
// in the file LICENSE.txt, which you should have received as part of this distribution. The 
// license terms are also available at http://www.opensource.org/licenses/ms-rl.html.

#include "wtkpc.h"

#include "wtk/ApplicationWindow.h"
#include "wtk/WindowClass.h"
#include "wtk/Error.h"

#include <iostream>

namespace wtk
{
	namespace
	{
		class ApplicationWindowClass 
		{
		public:

			ApplicationWindowClass()
			{
				WNDCLASSEXW wndClassEx;
				wndClassEx.cbSize = sizeof(wndClassEx);
				wndClassEx.style = 0;
				wndClassEx.lpfnWndProc = DefWindowProcW;
				wndClassEx.cbClsExtra = 0;
				wndClassEx.cbWndExtra = 0;
				wndClassEx.hInstance = NULL;
				wndClassEx.hIcon = NULL;
				wndClassEx.hCursor = win32::LoadCursorA(NULL, IDC_ARROW);
				wndClassEx.hbrBackground = win32::GetSysColorBrush(COLOR_BACKGROUND);
				wndClassEx.lpszMenuName = NULL;
				wndClassEx.lpszClassName = L"wtk::ApplicationWindow";
				wndClassEx.hIconSm = NULL;

				m_atom = win32::RegisterClassExW(&wndClassEx);
			}

			ApplicationWindowClass::~ApplicationWindowClass()
			{
				win32::UnregisterClassW(GetAtomAsClassName(), NULL);
			}

			LPCWSTR GetAtomAsClassName() 
			{ 
				return WindowClass::AtomToClassName(m_atom); 
			}

		private:

			ATOM m_atom;
		};

		ApplicationWindowClass ApplicationWindowClass;

		SIZE GetDesktopSize()
		{
			RECT rect;
			win32::GetWindowRect(win32::GetDesktopWindow(), &rect);
			return Construct<SIZE>(rect);
		}
	}

	ApplicationWindow::ApplicationWindow(const std::wstring &title)
		: Window(ApplicationWindowClass.GetAtomAsClassName(), NULL)
		, title(title)
	{
		this->style |= WS_CAPTION | WS_OVERLAPPED | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX | WS_SYSMENU;
		this->styleEx |= WS_EX_APPWINDOW;

		SIZE desktopSize = GetDesktopSize();

		this->position.x = desktopSize.cx / 20;
		this->position.y = desktopSize.cy / 20;
		this->size.cx = desktopSize.cx - 2 * this->position.x;
		this->size.cy = desktopSize.cy - 2 * this->position.y;
	}

	int ApplicationWindow::Run()
	{
		Menu &menuBar = GetMenuBar();

		menuBar.Create();

		Window::Create(title.c_str(), menuBar.handle);

		Window::DrawMenuBar();

		Window::Show(SW_MAXIMIZE);
		Window::Update();

		MSG msg;
		while (win32::GetMessageW(&msg, NULL, 0, 0)) {
			win32::TranslateMessage(&msg); 
			win32::DispatchMessageW(&msg); 
		}

		Window::Destroy();

		return msg.wParam;
	}

	LRESULT ApplicationWindow::ProcessMessage(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam)
	{
		if (message == WM_CLOSE) {
			win32::PostQuitMessage(0);
			return 0;
		} else {
			return Window::ProcessMessage(windowHandle, message, wParam, lParam);
		}
	}
}
